package com.jn.erp.web.api.student.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jn.erp.utils.DateUtils;
import com.jn.erp.web.api.common.enums.ErrorEnum;
import com.jn.erp.web.api.course.entity.TCourseOrder;
import com.jn.erp.web.api.course.entity.TCourseOrderDetail;
import com.jn.erp.web.api.course.mapper.TCourseOrderDetailMapper;
import com.jn.erp.web.api.course.mapper.TCourseOrderMapper;
import com.jn.erp.web.api.interaction.entity.TIntegral;
import com.jn.erp.web.api.interaction.entity.TIntegralConfig;
import com.jn.erp.web.api.interaction.mapper.TIntegralConfigMapper;
import com.jn.erp.web.api.interaction.mapper.TIntegralMapper;
import com.jn.erp.web.api.student.entity.Student;
import com.jn.erp.web.api.student.entity.StudentCourse;
import com.jn.erp.web.api.student.entity.TStudentClassRela;
import com.jn.erp.web.api.student.entity.TStudentCourseSale;
import com.jn.erp.web.api.student.entity.dto.StudentClassDto;
import com.jn.erp.web.api.student.entity.dto.TStudentCourseDto;
import com.jn.erp.web.api.student.entity.vo.StudentClassVo;
import com.jn.erp.web.api.student.entity.vo.StudentCourseVo;
import com.jn.erp.web.api.student.entity.vo.TStudentCourseVo;
import com.jn.erp.web.api.student.entity.vo.TransferOrderVo;
import com.jn.erp.web.api.student.mapper.StudentClassMapper;
import com.jn.erp.web.api.student.mapper.StudentCourseMapper;
import com.jn.erp.web.api.student.mapper.StudentMapper;
import com.jn.erp.web.api.student.mapper.TStudentCourseSaleMapper;
import com.jn.erp.web.api.student.service.StudentClassRelaService;
import com.jn.erp.web.api.student.service.StudentCourseService;
import com.jn.erp.web.api.student.service.StudentService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
public class StudentCourseServiceImpl extends ServiceImpl<StudentCourseMapper, StudentCourse> implements StudentCourseService {

   @Autowired
  private  StudentService studentService;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private TStudentCourseSaleMapper tStudentCourseSaleMapper;

    @Autowired
    private TCourseOrderMapper tCourseOrderMapper;

    @Autowired
    private TIntegralConfigMapper tIntegralConfigMapper;

    @Autowired
    private TIntegralMapper tIntegralMapper;

    @Autowired
    private TCourseOrderDetailMapper tCourseOrderDetailMapper;

    @Autowired
    private StudentClassRelaService studentClassRelaService;

    @Autowired
  private   StudentCourseMapper studentCourseMapper;


    @Autowired
    private StudentClassMapper studentClassMapper;

    static final String SELECT_REMAINING_FIELD = "count_lesson_total_normal - count_lesson_complete";
    @Override
    public int getTotalLessonRemainingCount(Long id) {
//        QueryWrapper<StudentCourse> qw = new QueryWrapper<>();
//        qw.eq("student_id", id);
//                .ge("expire_date", LocalDate.now().toString());
//                .select("sum(" + SELECT_REMAINING_FIELD + ") as total");
        StudentCourse studentCourses = studentCourseMapper.selectCounts(id);
        if (studentCourses != null) {
            int i = studentCourses.getCountLessonTotalNormal() - studentCourses.getCountLessonComplete();
            return i;
        } else {
            return 0;
        }


//        Map<String, Object> map = this.getMap(qw);
//        return (BigDecimal) map.get("total");
    }

    @Override
    public List<StudentCourse> addOne(StudentCourseVo studentCourseVo) {
            Student student = studentService.getById(studentCourseVo.getStudentId());
            // 在读学员报名还为在读
        if (student.getStage() == 2){
            student.setStage(2);
        }
        // 跟进和历史学员报名 把学员状态改为报读
        if (student.getStage() == 3 || student.getStage() == 5){
            student.setStage(4);
        }
            studentMapper.updateById(student);
        List<StudentCourse> postData = studentCourseVo.getPostData();
//
        List<StudentCourse> list = new ArrayList<>();
        for (StudentCourse stuCourse : postData) {
            stuCourse.setStudentId(studentCourseVo.getStudentId());
            list.add(stuCourse);
        }
        this.saveBatch(list);
        return list;
    }

    @Override
    public String application(StudentCourseVo studentCourseVo , Boolean flag) {
        List<TStudentCourseVo> tStudentCourseVos = studentCourseVo.gettStudentCourseVos();
        List<TStudentCourseSale> tStudentCourseSales = studentCourseVo.gettStudentCourseSales();

        //可能存在Redis容灾不生效的的情况取数据库数据进行初始化
        LocalDateTime sDate = LocalDateTime.now();
        StringBuffer sb = new StringBuffer();
        sb.append("BM").append(DateUtils.getString(sDate,"yyyyMMdd"));
        String key = "application"+":"+sb.toString();
        Boolean b = redisTemplate.hasKey(key);
        if(!b){
            String orderNo = studentCourseMapper.getMaxOrderNo(DateUtils.getString(sDate, "yyyyMMdd"),1);
            if(StringUtils.isNotBlank(orderNo)){
                orderNo = orderNo.substring(orderNo.length()-4,orderNo.length());
                redisTemplate.opsForValue().set(key,Integer.parseInt(orderNo));
            }

        }
        StringBuffer sb1 = new StringBuffer();
        sb1.append("XB").append(DateUtils.getString(sDate,"yyyyMMdd"));
        String key1 = "application"+":"+sb1.toString();
        Boolean b1 = redisTemplate.hasKey(key1);
        if(!b1){
            String orderNo = studentCourseMapper.getMaxOrderNo(DateUtils.getString(sDate, "yyyyMMdd"),2);
            if(StringUtils.isNotBlank(orderNo)){
                orderNo = orderNo.substring(orderNo.length()-4,orderNo.length());
                redisTemplate.opsForValue().set(key,Integer.parseInt(orderNo));
            }

        }

        List<StudentCourse> studentCourses = new ArrayList<>();
        StringBuffer stringBuffer = new StringBuffer();
        tStudentCourseVos.stream().forEach(u->{
            if(Objects.isNull(u.getType())){
                List<StudentCourse> list = baseMapper.selectList(new QueryWrapper<StudentCourse>().eq("deleted", "0").eq("student_id", u.getStudentId()));
                u.setType(CollectionUtils.isEmpty(list) ? 1 : 2 );
            }
            String head = "XB";
            switch (u.getType()){
                case 1:  head = "BM";break;
                case 2:  head = "XB";break;
                case 3:  head = "TK";break;
            }
          StudentCourse studentCourse = new StudentCourse(studentCourseVo.getOrgId(),getOrderNo(LocalDateTime.now(),"application",head),u.getOrderNoRefund()
                  ,u.getType(),studentCourseVo.getStudentId(),u.getCourseId(),u.getPriceId(),null,LocalDate.now(),u.getExpireDate(),u.getCountLessonTotalNormal()+u.getCountLessonTotalGive()
                  ,u.getCountLessonTotalNormal(),u.getCountLessonTotalGive(),0,0,u.getCourseAmount(),u.getDiscountAmount(),u.getOriginalUnitPrice(),u.getUnitPrice()
                  ,u.getAmount(),u.getPaidAmount(),1,u.getSource(),u.getPayType(),u.getOperator(),u.getVerifyState(),u.getWarningTimes(),1
                  ,u.getRemark(),studentCourseVo.getCreator(),LocalDateTime.now(),null,null,0);
            studentCourse.setHandlingTime(studentCourseVo.getHandlingTime());
            studentCourses.add(studentCourse);
            stringBuffer.append(studentCourse.getOrderNo()).append(",");
            //对试听课进行更新
            TCourseOrder audition = new TCourseOrder("1",DateUtils.getCurrentTime(),LocalDateTime.now(), Long.toString(studentCourseVo.getCreator()) );
            tCourseOrderMapper.update(audition,new QueryWrapper<TCourseOrder>().eq("student_id",studentCourseVo.getStudentId()).eq("course_id",u.getCourseId()).eq("temp","3"));
            if(flag){
                //添加积分
                TIntegralConfig t = tIntegralConfigMapper.selectOne(new QueryWrapper<TIntegralConfig>().eq("org_id", studentCourseVo.getOrgId()).eq("is_delete","0"));
                if(!Objects.isNull(t)){
                    TIntegral tIntegral = new TIntegral(studentCourseVo.getOrgId(),studentCourseVo.getStudentId(),t.getId(),1,t.getAttr1(),t.getName(),"报名",LocalDateTime.now(),String.valueOf(studentCourseVo.getCreator()) ,null,null,"0");
                    tIntegralMapper.insert(tIntegral);
                }
            }

        });
        this.saveBatch(studentCourses);
        if (stringBuffer.length() > 0) {
            stringBuffer.setLength(stringBuffer.length() - 1); // 移除最后一位字符
        }
        tStudentCourseSales.stream().forEach(u->{
            u.setType(studentCourses.get(0).getType());
            u.setOrgId(studentCourseVo.getOrgId());
            u.setOrderNo(stringBuffer.toString());
            u.setCreator(studentCourseVo.getCreator());
            u.setAddTime(LocalDateTime.now());
            u.setHandlingTime(studentCourseVo.getHandlingTime());
            tStudentCourseSaleMapper.insert(u);
        });


        Student student = studentService.getById(studentCourseVo.getStudentId());

        // 在读学员报名还为在读
        if (student.getStage() == 2 ){
            student.setStage(2);
        } else {
            // 线索跟进和历史学员报名 把学员状态改为报读
            student.setStage(4);
        }
        studentMapper.updateById(student);
        return "S200";
    }

    @Override
    public List<TStudentCourseDto> studentCourseList(TStudentCourseVo tStudentCourseVo) {
        List<TStudentCourseDto> list = baseMapper.studentCourseList(tStudentCourseVo);
        return list;
    }

    @Override
    public TStudentCourseDto studentCourseDetail(TStudentCourseVo tStudentCourseVo) {
        TStudentCourseDto tStudentCourseDto = baseMapper.studentCourseDetail(tStudentCourseVo);
        return tStudentCourseDto;
    }

    @Override
    public List<TStudentCourseSale> salerList(TStudentCourseVo tStudentCourseVo) {
        List<TStudentCourseSale> tStudentCourseSales = tStudentCourseSaleMapper.selectList(new QueryWrapper<TStudentCourseSale>().eq("deleted","0").eq("order_no",tStudentCourseVo.getOrderNo()));
        return tStudentCourseSales;
    }

    @Override
    public List<TStudentCourseDto> courseList(TStudentCourseVo tStudentCourseVo) {
        List<TStudentCourseDto> list = baseMapper.courseList(tStudentCourseVo);
        return list;
    }

    @Override
    public List<TStudentCourseDto> courseOrderList(TStudentCourseVo tStudentCourseVo) {
        List<TStudentCourseDto> list = baseMapper.courseOrderList(tStudentCourseVo);
        return list;
    }

    @Override
    public String refundOrder(List<TStudentCourseVo> tStudentCourseVos) {
        //可能存在Redis容灾不生效的的情况取数据库数据进行初始化
        LocalDateTime sDate = LocalDateTime.now();
        StringBuffer sb = new StringBuffer();
        sb.append("TK").append(DateUtils.getString(sDate,"yyyyMMdd"));
        String key = "refundOrder"+":"+sb.toString();
        Boolean b = redisTemplate.hasKey(key);
        if(!b){
            String orderNo = studentCourseMapper.getMaxOrderNo(DateUtils.getString(sDate, "yyyyMMdd"),3);
            if(StringUtils.isNotBlank(orderNo)){
                orderNo = orderNo.substring(orderNo.length()-4,orderNo.length());
                redisTemplate.opsForValue().set(key,Integer.parseInt(orderNo));
            }
        }

        List<StudentCourse> studentCourses = new ArrayList<>();
        tStudentCourseVos.stream().forEach(u->{
            StudentCourse sc = baseMapper.selectOne(new QueryWrapper<StudentCourse>().eq("deleted", 0).eq("order_no", u.getOrderNo()));
            //原订单结课退课
            u.setCountLessonRefund(u.getRefundLessonNormal()+u.getRefundLessonGive());
            u.setExhausted(0);
            u.setEditTime(LocalDateTime.now());
            baseMapper.updateById(u);
            //生成退课订单
             String head = "TK";
             StudentCourse studentCourse = new StudentCourse(u.getOrgId(),getOrderNo(LocalDateTime.now(),"refundOrder",head),u.getOrderNo()
                        ,3,u.getStudentId(),u.getCourseId(),sc.getPriceId(),null,LocalDate.now(),sc.getExpireDate(),u.getRefundLessonNormal()+u.getRefundLessonGive()
                        ,u.getRefundLessonNormal(),u.getRefundLessonGive(),0,u.getRefundLessonNormal()+u.getRefundLessonGive(),sc.getCourseAmount(),sc.getDiscountAmount(),sc.getOriginalUnitPrice(),sc.getUnitPrice()
                        ,u.getRefundAmount(),u.getRefundAmount(),1,sc.getSource(),sc.getPayType(),u.getOperator(),sc.getVerifyState(),sc.getWarningTimes(),0
                        ,u.getRemark(),u.getEditor(),LocalDateTime.now(),null,null,0);
            studentCourse.setHandlingTime(u.getHandlingTime());
            studentCourses.add(studentCourse);
        });

        this.saveBatch(studentCourses);
        return "S200";
    }

    @Override
    public BigDecimal sumAmount(TStudentCourseVo tStudentCourseVos) {
        BigDecimal bigDecimal = baseMapper.sumAmount(tStudentCourseVos);
        return bigDecimal;
    }

    @Override
    public List<TStudentCourseDto> listSecond(TStudentCourseVo tStudentCourseVo) {
        tStudentCourseVo.setListType("2");
        List<TStudentCourseDto> list = baseMapper.listSecond(tStudentCourseVo);
        list.stream().forEach(u->{
            if(StringUtils.isNotBlank(u.getClassId())){
                List<String> list1 = Arrays.asList(u.getClassId().split(","));
                u.setClassIdArr(list1);
            }
            tStudentCourseVo.setCourseId(u.getCourseId());
            List<TStudentCourseDto> tStudentCourseDtos = baseMapper.studentCourseList(tStudentCourseVo);
            u.setTStudentCourseDtos(tStudentCourseDtos);
            StudentClassVo studentClassVo = new StudentClassVo();
            studentClassVo.setCourseId(u.getCourseId().toString());
            studentClassVo.setOrgId(tStudentCourseVo.getOrgId());
            studentClassVo.setBeOver(1L);
            studentClassVo.setIsVip(u.getLessonType());
            studentClassVo.setIsRepair(1);
            List<StudentClassDto> studentClassDtos = studentClassMapper.classList(studentClassVo);
            u.setStudentClassDtos(studentClassDtos);
        });
        return list;
    }

    @Override
    public String transferOrder(TransferOrderVo transferOrderVo) {
        refundOrder(transferOrderVo.gettStudentCourseVos());
        application(transferOrderVo.getStudentCourseVo(),false);
        return "S200";
    }

    @Override
    public String dealExceed(TStudentCourseVo tStudentCourseVos) {
        StudentCourse studentCourse = baseMapper.selectById(tStudentCourseVos.getId());
        Integer exceed = studentCourse.getCountLessonComplete() - studentCourse.getCountLessonTotal();
        if(exceed <= 0 ){
            throw new RuntimeException(ErrorEnum.E105.getName());
        }
        List<StudentCourse> tStudentCourseDtos = baseMapper.listThird(studentCourse);
        Integer temp = exceed;
        Integer add = 0;
        //只进行正常课时的扣除
        for (StudentCourse tStudentCourseDto : tStudentCourseDtos) {
            if(exceed == 0){
                break;
            }
            if(tStudentCourseDto.getRemainderLessonNormal() > exceed){
                tStudentCourseDto.setCountLessonComplete(tStudentCourseDto.getCountLessonComplete() + exceed );
                exceed = 0;
            }else{
                tStudentCourseDto.setCountLessonComplete(tStudentCourseDto.getCountLessonTotalNormal());
                exceed -= tStudentCourseDto.getRemainderLessonNormal();
            }
            tStudentCourseDto.setEditor(tStudentCourseVos.getEditor());
            tStudentCourseDto.setEditTime(LocalDateTime.now());
            baseMapper.updateById(tStudentCourseDto);
            TCourseOrderDetail tCourseOrderDetail = new TCourseOrderDetail(tStudentCourseDto.getOrgId(),null,tStudentCourseDto.getOrderNo(),3,temp -exceed - add,temp -exceed - add,0,"超时点名扣除",LocalDateTime.now(),tStudentCourseVos.getEditor().toString(),null,null,"0");
            tCourseOrderDetailMapper.insert(tCourseOrderDetail);
            add += temp -exceed;
        }
        if(exceed > 0){
            throw new RuntimeException(ErrorEnum.E106.getName());
        }else{
            studentCourse.setCountLessonComplete(studentCourse.getCountLessonTotal());
            studentCourse.setEditor(tStudentCourseVos.getEditor());
            studentCourse.setEditTime(LocalDateTime.now());
            baseMapper.updateById(studentCourse);
            TCourseOrderDetail tCourseOrderDetail = new TCourseOrderDetail(studentCourse.getOrgId(),null,studentCourse.getOrderNo(),3,-temp,-temp,0,"超时点名回退",LocalDateTime.now(),tStudentCourseVos.getEditor().toString(),null,null,"0");
            tCourseOrderDetailMapper.insert(tCourseOrderDetail);
        }
        return ErrorEnum.S200.getName();
    }

    @Override
    public String classEnding(TStudentCourseVo tStudentCourseVos) {
        dealClassEnding(tStudentCourseVos,2);
        return ErrorEnum.S200.getName();
    }

    @Override
    public String stopsAndResume(TStudentCourseVo tStudentCourseVos) {
        if(tStudentCourseVos.getStopsResume() == 0){
            //成员移除班级
            TStudentClassRela tStudentClassRela = new TStudentClassRela();
            tStudentClassRela.setDeleted(1);
            tStudentClassRela.setEditor(tStudentCourseVos.getEditor());
            tStudentClassRela.setEditTime(LocalDateTime.now());
            studentClassRelaService.update(tStudentClassRela,new QueryWrapper<TStudentClassRela>().eq("student_id",tStudentCourseVos.getStudentId()).eq("deleted","0"));
            //课次处理
            TCourseOrder tCourseOrder = new TCourseOrder();
            tCourseOrder.setIsDelete("1");
            tCourseOrder.setUpdateUser(tStudentCourseVos.getEditor().toString());
            tCourseOrder.setUpdateDate(LocalDateTime.now());
            //需添加当天大于等于开课时间
            this.tCourseOrderMapper.update(tCourseOrder,new QueryWrapper<TCourseOrder>().eq("student_id",tStudentCourseVos.getStudentId()).eq(!Objects.isNull(tStudentCourseVos.getCourseId()),"course_id",tStudentCourseVos.getCourseId())
                    .ge("class_date",LocalDateTime.now()).eq("state","1"));
        }
        baseMapper.update(tStudentCourseVos, new QueryWrapper<StudentCourse>().eq("student_id",tStudentCourseVos.getStudentId()).eq(!Objects.isNull(tStudentCourseVos.getCourseId()),"course_id",tStudentCourseVos.getCourseId()).eq("deleted","0"));
        return ErrorEnum.S200.getName();
    }

    public  String dealClassEnding(TStudentCourseVo tStudentCourseVos,Integer exhaustedType){
        //订单清零
        StudentCourse studentCourse = new StudentCourse();
        studentCourse.setExhausted(0);
        studentCourse.setEditor(tStudentCourseVos.getEditor());
        studentCourse.setEditTime(LocalDateTime.now());
        studentCourse.setExhaustedType(exhaustedType);
        baseMapper.update(studentCourse,new QueryWrapper<StudentCourse>().eq("student_id",tStudentCourseVos.getStudentId()).eq(!Objects.isNull(tStudentCourseVos.getCourseId()),"course_id",tStudentCourseVos.getCourseId()).eq("deleted","0"));
        //成员移除班级
        TStudentClassRela tStudentClassRela = new TStudentClassRela();
        tStudentClassRela.setDeleted(1);
        tStudentClassRela.setEditor(tStudentCourseVos.getEditor());
        tStudentClassRela.setEditTime(LocalDateTime.now());
        studentClassRelaService.update(tStudentClassRela,new QueryWrapper<TStudentClassRela>().eq("student_id",tStudentCourseVos.getStudentId()).eq("deleted","0"));
        //课次处理
        TCourseOrder tCourseOrder = new TCourseOrder();
        tCourseOrder.setIsDelete("1");
        tCourseOrder.setUpdateUser(tStudentCourseVos.getEditor().toString());
        tCourseOrder.setUpdateDate(LocalDateTime.now());
        //需添加当天大于等于开课时间
        this.tCourseOrderMapper.update(tCourseOrder,new QueryWrapper<TCourseOrder>().eq("student_id",tStudentCourseVos.getStudentId()).eq(!Objects.isNull(tStudentCourseVos.getCourseId()),"course_id",tStudentCourseVos.getCourseId())
                .ge("class_date",LocalDateTime.now()).eq("state","1"));
        return ErrorEnum.S200.getName();
    }

    private String getOrderNo(LocalDateTime classDate ,String keyHead ,String head){
        String classDateStr = DateUtils.getString(classDate, "yyyy-MM-dd");
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(head).append(DateUtils.getString(classDate,"yyyyMMdd"));
        String key = keyHead+":"+stringBuffer.toString();
        //这里是 Redis key的前缀，如: sys:日期
        Long autoID = redisTemplate.opsForValue().increment(key, 1);
        // 设置key过期时间, 保证每天的流水号从1开始
//        if (autoID == 1) {
//            redisTemplate.expire(key, 1, TimeUnit.DAYS);
//        }
        if(autoID<10000){
            String num = StringUtils.leftPad(String.valueOf(autoID), 4, "0");
            stringBuffer.append(num);
            return stringBuffer.toString();
        } else {
            throw  new RuntimeException("当日课程编号已取完！");
        }
    }


}